BaseSynthDescriptor : OrderedEnvir{

	var c;

	*new{
		^super.new.init;	
	}
	
	*loadAllSynths{
		var loadSubs;
		
		this.loadBaseSynths;
		
		loadSubs = {|class|
			class.subclasses.do{|subClass|
				subClass.loadSynth;
				loadSubs.value(subClass);
			}
		};
		
		loadSubs.value(this);
	}
	
	*getCPUIndex{
		^1;
	}
	
	*balanceCheckbook{|time|
		OverloadPreventer.voiceLaunched(this.getCPUIndex, time);
	}
	
	init{
		this.createControlsList;
		this.createGuiControls;
	}
	
	createControlsList{
		c = FloatDataControl; 
		///this.put(\out1Level, 		c.new(default: 1) );
		this.put(\triggerFreq,  	c.new(default: 10, min: 0.1, max: 30, theLog: 3,  midiNum:14, postLaunch: true ) );
		this.put(\volume, 		c.new(default: 1, midiNum:12) );
		this.put(\volume2, 		c.new(default: 1, max: 5, theLog: 2, postLaunch: true, midiNum:13 ) );
		this.put(\out2Level, 		c.new(default: 0) );
		this.put(\fxLevel, 		c.new(default: 0, max:0.2,  postLaunch: true ) );
		this.put(\instances,  	c.new(default: 1, min: 1, max: 20,  midiNum:14) );
		this.put(\pan, 			c.new(default: 0, min:-1, max: 1,  midiNum:15) );
		this.put(\attack, 		c.new(default: 0.05, min:0, max: 3,  midiNum:17, theLog:3) );
		this.put(\decay, 			c.new(default: 0, min: 0.02, max: 0.5,  midiNum:16) );
		this.put(\sustain, 		c.new(default: 1, min:0.001, max: 1,  midiNum:17) );
		this.put(\release, 			c.new(default: 0.05,min: 0.01, max: 5,  midiNum:18) );
		this.put(\mainEnvCurve, 	c.new(default: 0, max: 10, min: -10,  midiNum:19) );
		this.put(\tremeloDepth, 	c.new(default: 0, max: 1, min: 0) );
		this.put(\tremeloRate, 	c.new(default: 0, max: 50, min: 0,  theLog: 2) );
	}
	
	// override in sublcass;
	createGuiControls{
	
	}
	
	*loadSynth{
	
	}
	
	*playSound{|args, group|
		Synth(this.getSynthName, args, group);
	}
	
	*onPlaySound{}	
	
	*getSynthName{
		^this.name;
	}
	
	*getOutSynthName{
		^\OutSynth; 
	}
	
	*getPlayerClass{
		^RipplePlayer;
	}
	
	*loadBaseSynths{
	"loading base synths".postln;
		SynthDef(\OutSynth,{|busNum, attack, decay, sustain, release, mainEnvCurve, volume, volume2, pan, gate=1, tremeloDepth, tremeloRate, fxLevel = 0, out1Level = 1, out2Level = 0, mainOutBus|
			var out, env, ampEnv, outVol;
			
			env = Env([0, 1, sustain, 0], [attack, decay, release], mainEnvCurve);
			ampEnv =  EnvGen.kr(env, doneAction: 14);
			volume2 = Lag.kr(volume2, 2);
			outVol = volume * volume2;
			
			out =  Balance2.ar( 
					In.ar(busNum, 2)[0] * ampEnv,
					In.ar(busNum, 2)[1] * ampEnv,
					pan
				);
			
			out = out * (1 - (SinOsc.kr(tremeloRate) * tremeloDepth));
			
			Out.ar(mainOutBus, out * outVol );
			Out.ar(SynthConstants.getFXBus, out * fxLevel * outVol);
			Out.ar(SynthConstants.getBufferRecordBus, out * out2Level * 5);
			
			
		}).send(Server.default);
	}
	
	*createSynthName{
		^this.getSynthName.asString;
	}
	
	*getBehaviorClasses{
		^nil;	
	}
	
	*getPlayerFactoryClass{
		// abstract method. shouldn't ever be called	
	}

}

SimpleSynthDescriptor : BaseSynthDescriptor{	
	*createSynthName{|name|
		//^"synth";
		^this.name.asString
	}	
	
	*getPlayerFactoryClass{
		^NoSamplePlayerFactory;	
	}

}

SampleSynthDescriptor : BaseSynthDescriptor{
	
	*getPlayerFactoryClass{
		^SamplePlayerFactory;	
	}
	
	*createSynthName{|name|
		^name;
	}

	createControlsList{
		super.createControlsList;
		this.put(\startOffset, 	c.new(default: 0, midiNum: 99, max: 0.99) );
	}
}